/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package my.cbr.similarity;

import de.dfki.mycbr.XMLConstants;
import de.dfki.mycbr.model.similaritymeasures.AbstractSMFunction;
import de.dfki.mycbr.model.similaritymeasures.smftypes.SMF_Number_Advanced;
import de.dfki.mycbr.model.vocabulary.ModelInstance;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import jcolibri.exception.NoApplicableSimilarityFunctionException;
import jcolibri.method.retrieve.NNretrieval.similarity.LocalSimilarityFunction;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.filter.ElementFilter;
import org.jdom.input.SAXBuilder;

/**
 *
 * @author Geir Ole
 */
public class DateSimilarity implements LocalSimilarityFunction{

    public AbstractSMFunction smf = null;

    /**
     * Constructor.
     * @param configFilePath is the path to the XML file generated with MyCBR
     */
    public DateSimilarity(String configFilePath)
    {
        try {
            SAXBuilder saxBuilder = new SAXBuilder();
            Document docSMF = saxBuilder.build(jcolibri.util.FileIO.findFile(configFilePath));
            for (Iterator fctIt = docSMF.getContent(new ElementFilter(XMLConstants.XML_TAG_SMFUNCTION)).iterator(); fctIt.hasNext();)
            {
                // get next similarity function
                Element smfElement = (Element) fctIt.next();

                // according slot
                Attribute att = smfElement.getAttribute(XMLConstants.XML_ATT_MODEL_INSTNAME);
                String instname = att.getValue();

                Attribute attype = smfElement.getAttribute(XMLConstants.XML_ATT_TYPE);
                String insttype = attype.getValue();

                ArrayList<Object> av = new ArrayList<Object>();
                ModelInstance instance = new PuppetModelInstance(instname, insttype, av);

                smf = new SMF_Number_Advanced(instance,smfElement);
            }
        } catch (Exception e) {
            org.apache.commons.logging.LogFactory.getLog(this.getClass()).error("Error initializing Date similarity function");
        }
    }

    /**
     * 
     * @param caseObject
     * @param queryObject
     * @return the similarity between the inputs. double range [0..1]
     * @throws NoApplicableSimilarityFunctionException
     */
    public double compute(Object caseObject, Object queryObject) throws NoApplicableSimilarityFunctionException
    {
        // Check the input
        if(caseObject==null || queryObject==null)
            return 0;
        if (!(caseObject instanceof Date))
            throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), caseObject.getClass());
        if (!(queryObject instanceof Date))
            throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), queryObject.getClass());
        
        Date caseDate = (Date) caseObject;
        Date queryDate = (Date) queryObject;

        // Find the day of year in date
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(queryDate);
        int queryDateOfYear = calendar.get(Calendar.DAY_OF_YEAR);
        calendar.setTime(caseDate);
        int caseDateOfYear = calendar.get(Calendar.DAY_OF_YEAR);

        // compute similarity
        double res = 0;
        try {
                res = smf.getSimilarityBetween(queryDateOfYear, caseDateOfYear, null);
        } catch (Exception e) {
                org.apache.commons.logging.LogFactory.getLog(this.getClass()).error("Error executing MyCBR similarity function");
        }
        return res;
    }

    /** Checks if both objects are of type java.util.Date
     *
     * @param caseObject
     * @param queryObject
     * @return true if both objects are of type java.util.Date
     */
    public boolean isApplicable(Object caseObject, Object queryObject) {
            return (caseObject instanceof Date)&&(queryObject instanceof Date);
    }

}
